package com.imooc.netty;

import com.imooc.netty.websocket.WSServerInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * Netty服务器  (用的是主从线程组模型)
 * @author liansen
 * @create 07-14-23:32
 */
public class NettyServer {

    public static void main(String[] args) throws Exception {

        //定义主从线程组
        /**
         * 定义主线程组, 用于接收客户端连接, 但是不做任何处理
         * 就像老板在外面拉到业务，具体执行是交给员工处理的
         */
        EventLoopGroup bossGroup = new NioEventLoopGroup();

        /**
         * 定义从线程组/工作线程组,
         * 从线程组用来处理主线程组丢过来的任务
         */
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            //创建netty服务器
            ServerBootstrap server = new ServerBootstrap(); //定义启动类
            //绑定关系
            server.group(bossGroup, workerGroup)    //绑定主从线程组
                    .channel(NioServerSocketChannel.class)  //设置nio的双向通道channel, 双向意思是客户端和服务端通信，服务端和客户端通信
                    .childHandler(new WSServerInitializer()); //处理器，用于处理从线程组丢过来的任务


            /**
             * 启动netty服务器server, 并绑定端口, 同时以同步方式启动;
             * Netty里面的IO操作全部是异步的。这意味着，IO操作会立即返回，但是在调用结束时，
             * 无法保证IO操作已完成。取而代之，将会返回给你一个ChannelFuture 实例，提供IO操作的结果信息或状态
             */
            ChannelFuture channelFuture = server.bind(875).sync();

            //监听关闭的channel
            channelFuture.channel().closeFuture().sync();
        }finally {

            //关闭主从线程组
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
